<?php

namespace app\common;

use think\Image;
use think\facade\Session;
use think\facade\Filesystem;
use think\exception\ValidateException;
use think\Validate;
use app\common\model\Files as FilesModel;
use finfo;
use helper\ApkParser;
use helper\Wechat as WechatHelper;
use League\Flysystem\FileNotFoundException;
use Qcloud\Cos\Client as QcloudClient;
use Qiniu\Auth as QiniuClient;
use Qiniu\Storage\UploadManager as QiniuUploadManager;
use OSS\OssClient as AliyunOssClient;
use OSS\Core\OssException as AliyunOssException;
use TencentCloud\Tcb\V20180608\Models\ExtensionFile;

class UploadFile
{
    /**
     * 本机模拟客户端上传文件
     *
     * @author 邓启航 <lingshu@xycms.com>
     * @param string $fileName 模拟表单参数名
     * @param string $tmpName 文件临时缓存目录
     * @param string $pathParameter 系统管理的路由
     * @return void
     */
    public static function localUploadImage(string $fileName, string $tmpName, $pathParameter)
    {
        // 如果有传入管理路由则伪造对应参数
        if ($pathParameter) {
            $_POST['path'] = $pathParameter;
            request()->withPost($_POST);
        }
        /*  通常$_FILES的格式如下：
        [
            '表单文件字段名' => [
                'name' => '客户端文件名',   // 注意，如果有验证器验证后缀名，会针对这个字段验证
                'type' => 'MINE TYPE',
                'tmp_name' => '文件缓存目录',
                'error' => 0,
                'size' => 文件流长度
            ]
        ]*/
        // 如果文件不存在则抛异常
        if (!file_exists($tmpName)) {
            throw new FileNotFoundException($tmpName);
        }

        // 获取文件mine-type
        $finfo = finfo_open(FILEINFO_MIME);
        $mineType =  explode(';', finfo_file($finfo, $tmpName))[0];
        finfo_close($finfo);
        // 获取文件size
        $fileSize = filesize($tmpName);
        // 给临时文件改个名
        $extTransform = [
            'image/jpeg' => 'jpeg',
            'image/png'  => 'png',
            'image/bmp'  => 'bmp',
            'image/gif'  => 'gif',
        ];
        $ext = $extTransform[$mineType] ?? '';
        if (rename($tmpName, $tmpName . ".$ext")) {
            $tmpName = $tmpName . ".$ext";
        }
        // 伪造$_FILES参数
        $_FILES[$fileName] = [
            'name' => basename($tmpName),
            'type' => $mineType,
            'tmp_name' => $tmpName,
            'error' => 0,
            'size' => $fileSize
        ];
        request()->withFiles($_FILES);
        $result = self::upload(0, $fileName);
        // 删除临时文件
        @unlink($tmpName);
        return $result;
    }

    public static function upload($uid = 0, $formFile = 'file')
    {
        $D = request()->post();
        $files = request()->file($formFile);
        $is_admin = 0;
        if (empty($D['path'])) {
            $path = $formFile;
        } else {
            $path = $D['path'];
        }
        $filesize = config('xy_upconfig.filesize') * 1024;
        $fileExt = config('xy_upconfig.fileExt');
        $imgExt = config('xy_upconfig.imgExt');
        $videoExt = config('xy_upconfig.videoExt');
        $rule = [
            'filesize'  =>  0,
            'fileExt'   =>  '',
        ];

        switch ($path) {
            case 'web/img':
                $rule = [
                    'filesize'    =>    $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 0;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'user/headimg':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 1;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'article/thumb':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 3;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'publics/files':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $fileExt,
                ];
                $type = 2;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'article/content':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 4;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'article/video':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $videoExt,
                ];
                $type = 5;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'article/file':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $fileExt,
                ];
                $type = 6;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'company/business_license':
                $update_business_license_size = config('xy_company.update_business_license_size');
                $rule = [
                    'filesize'  =>  $update_business_license_size ? $update_business_license_size * 1024 : $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 7;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'company/logo':
                $update_logo_size = config('xy_company.update_logo_size');
                $rule = [
                    'filesize'  =>  $update_logo_size ? $update_logo_size * 1024 : $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 8;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'ads/image':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 9;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'company/executives_headimg':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 10;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'company/demeanor':
                $company_demeanor_size = config('xy_company.company_demeanor_size');
                $rule = [
                    'filesize'  =>  $company_demeanor_size ? $company_demeanor_size * 1024 : $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 11;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'menu/icon':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 12;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'jobs/icon':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 13;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'vip/icon':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 13;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'resume/works':
                $update_resume_works_size = config('xy_resume.update_resume_works_size');
                $rule = [
                    'filesize'  =>  $update_resume_works_size ? $update_resume_works_size * 1024 : $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 14;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'file/apk':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  'apk',
                ];
                $type = 15;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'file/wgt':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  'wgt',
                ];
                $type = 16;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'job_fair/thumb':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 17;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'job_fair/banner':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 18;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'admin/headimg':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 19;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'admin/other_img':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 20;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'real_name/img1':
            case 'real_name/img2':
            case 'real_name/img3':
            case 'real_name/img4':
            case 'real_name/img5':
                $rule = [
                    'filesize'  =>  5242880,
                    'fileExt'   =>  'png,jpg,jpeg',
                ];
                $type = 21;
                if (!$uid) {
                    $is_admin = 1;
                    $uid = Session::get('AdminUser.uid', 'bsadmin');
                }
                break;
            case 'job_fair/booth_img':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 22;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'posters/image':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 23;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'crm/screenshot':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 24;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'wechat/keywords/image':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $imgExt,
                ];
                $type = 25;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'wechat/keywords/video':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'   =>  $videoExt,
                ];
                $type = 26;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'special_topic/top_img':
            case 'special_topic/pc_side_img':
            case 'special_topic/pc_thumb':
            case 'special_topic/pc_bg':
            case 'special_topic/mobile_thumb':
            case 'special_topic/mobile_bg':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 27;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'work_wechat/alive_qr':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 28;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 'bsadmin');
                break;
            case 'work_wechat/avatar':
                $rule = [
                    'filesize'  =>  $filesize,
                    'fileExt'    =>    $imgExt,
                ];
                $type = 29;
                $is_admin = 1;
                $uid = Session::get('AdminUser.uid', 0);
                break;
        }
        $msg = [
            'file.filesize' =>  '上传大小超过限制(' . formatFileSize(round($rule['filesize'])) . ')',
            'file.fileExt'  =>  '文件类型不正确(' . strtoupper($rule['fileExt']) . ')',
        ];
        try {
            validate(['file' => $rule], $msg)->check(['file' => $files]);
            $saveName = Filesystem::disk('public')->putFile($path, $files);
            $root_path = Filesystem::getDiskConfig('public', 'url', config('xy_upconfig.save_path')) . '/';
            $saveFile = $root_path . $saveName;
            $status = 0;
            if (config('xy_oss.status')) {
                switch (config('xy_oss.service_provider')) {
                    case 'aliyun':
                        $status = self::updateAliyunOss($saveFile, $saveName);
                        break;
                    case 'qcloud':
                        $status = self::updateTencentQcloud($saveFile);
                        break;
                    case 'qiniu':
                        $status = self::updateQiniu($saveFile, $saveName);
                        break;
                }
            }
            $filesModel = new FilesModel;
            $filesModel->type = $type;
            $filesModel->is_admin = $is_admin;
            $filesModel->uid = $uid;
            $filesModel->path = $saveFile;
            $filesModel->status = $status;
            $filesModel->mime = $files->getMime();
            $filesModel->ext = $files->extension();
            $filesModel->size = $files->getSize() / 1024;
            switch ($path) {
                case 'wechat/keywords/image':
                    $WechatHelperRet = WechatHelper::updateMaterial(str_replace('/uploads', 'uploads', $saveFile), 'image');
                    $filesModel->media_id = $WechatHelperRet->media_id;
                    break;
                case 'wechat/keywords/video':
                    $WechatHelperRet = WechatHelper::updateMaterial(str_replace('/uploads', 'uploads', $saveFile), 'video');
                    $filesModel->media_id = $WechatHelperRet->media_id;
                    break;
            }
            if ($filesModel->save()) {
                switch ($path) {
                    case 'web/img':
                    case 'publics/files':
                        $data = [
                            'fid'   =>  $filesModel->id,
                            'id'    =>  isset($D['id']) ? $D['id'] : 0,
                            'ctype' =>  isset($D['ctype']) ? $D['ctype'] : '',
                            'index' =>  isset($D['index']) ? $D['index'] : '',
                            'type'  =>  $path,
                            'path'  =>  $saveFile,
                            'url'   =>  config('web.imgurl') . $saveFile
                        ];
                        break;
                    case 'wechat/keywords/image':
                    case 'wechat/keywords/video':
                        $data = [
                            'fid'   =>  $filesModel->id,
                            'type'  =>  $path,
                            'path'  =>  $saveFile,
                            'url'   =>  config('web.imgurl') . $saveFile,
                            'media_id' =>  $WechatHelperRet->media_id
                        ];
                        break;
                    case 'article/content':
                    case 'article/video':
                    case 'article/file':
                        $data = [
                            'type'      =>  $path,
                            'path'      =>  $saveFile,
                            'name'      =>  $D['name'],
                            'file_type' =>  $files->getType(),
                            'file_size' =>  $files->getSize(),
                            'url'       =>  config('web.imgurl') . $saveFile
                        ];
                        break;
                    case 'file/apk':
                        $appObj = new ApkParser();
                        $appObj->open(str_replace('/uploads', 'uploads', $saveFile));
                        $data = [
                            'fid'           =>  $filesModel->id,
                            'type'          =>  $path,
                            'path'          =>  $saveFile,
                            'file_type'     =>  $files->getType(),
                            'file_size'     =>  $files->getSize(),
                            'app_name'      =>  $appObj->getAppName(),
                            'package'       =>  $appObj->getPackage(),
                            'version_name'  =>  $appObj->getVersionName(),
                            'version_code'  =>  $appObj->getVersionCode()
                        ];
                        break;
                    case 'article/thumb':
                    default:
                        $data = [
                            'fid'   =>  $filesModel->id,
                            'type'  =>  $path,
                            'path'  =>  $saveFile,
                            'url'   =>  config('web.imgurl') . $saveFile
                        ];
                        break;
                }
                $ret = [
                    'msg'       =>  '上传成功',
                    'code'      =>  0,
                    'data'      =>  $data
                ];
            } else {
                @unlink(root_path() . 'public' . $saveFile);
                $ret = ['msg' => '保存失败', 'code' => -100];
            }
        } catch (\think\exception\ValidateException $e) {
            $ret = ['msg' => $e->getError(), 'code' => -100];
        } catch (\think\Exception $e) {
            $ret = ['msg' => $e->getMessage(), 'code' => -100];
        }
        return $ret;
    }
    public static function downWxAvatar($url, $uid = 0)
    {
        $path = config('xy_upconfig.save_path') . '/wx_avatar/';
        if (!file_exists($path))
            mkdir($path, 0777, true);
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $content = curl_exec($ch);
        $ContentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        $FileSize = curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD);
        curl_close($ch);
        // $content = file_get_contents($url);
        if (!$content) return ['msg' => '图片获取失败', 'code' => -100];
        if (strpos($ContentType, 'image') === false) return ['msg' => '返回内容不是图片', 'code' => -100];
        $fileExt = '';
        switch ($ContentType) {
            case 'image/jpeg':
                $fileExt = 'jpg';
                break;
            case 'image/png':
                $fileExt = 'png';
                break;
            case 'image/gif':
                $fileExt = 'gif';
                break;
            default:
                $fileExt = 'png';
                break;
        }
        $fileName = md5(time() . GetRand()) . '.' . $fileExt;
        $saveFile = $path . $fileName;
        file_put_contents($saveFile, $content);
        $status = 0;
        if (config('xy_oss.status')) {
            switch (config('xy_oss.service_provider')) {
                case 'aliyun':
                    $status = self::updateAliyunOss($saveFile, $fileName);
                    break;
                case 'qcloud':
                    $status = self::updateTencentQcloud($saveFile);
                    break;
                case 'qiniu':
                    $status = self::updateQiniu($saveFile, $fileName);
                    break;
            }
        }
        $filesModel = new FilesModel;
        $filesModel->type = 99;
        $filesModel->is_admin = 0;
        $filesModel->uid = $uid;
        $filesModel->path = '/' . $saveFile;
        $filesModel->status = $status;
        $filesModel->ext = $fileExt;
        $filesModel->mime = $ContentType;
        if ($filesModel->save()) {
            $ret = [
                'msg'       =>  '上传成功',
                'code'      =>  0,
                'data'      =>  [
                    'fid'   =>  $filesModel->id,
                    'path'  =>  '/' . $saveFile,
                    'url'   =>  config('web.imgurl') . '/' . $saveFile
                ]
            ];
        } else {
            @unlink(root_path() . 'public' . $saveFile);
            $ret = ['msg' => '保存失败', 'code' => -100];
        }
        return $ret;
    }
    public static function downImage($action, $url)
    {
        if (!$action) return ['msg' => '保存路径不能为空', 'code' => -100];
        $path = config('xy_upconfig.save_path') . '/' . $action;
        if (!file_exists($path))
            mkdir($path, 0777, true);
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $content = curl_exec($ch);
        $ContentType = curl_getinfo($ch, CURLINFO_CONTENT_TYPE);
        $FileSize = curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD);
        curl_close($ch);
        // $content = file_get_contents($url);
        if (!$content) return ['msg' => '图片获取失败', 'code' => -100];
        if (strpos($ContentType, 'image') === false) return ['msg' => '返回内容不是图片', 'code' => -100];
        $fileExt = '';
        switch ($ContentType) {
            case 'image/jpeg':
                $fileExt = 'jpg';
                break;
            case 'image/png':
                $fileExt = 'png';
                break;
            case 'image/gif':
                $fileExt = 'gif';
                break;
            default:
                $fileExt = 'png';
                break;
        }
        $fileName = md5(time() . GetRand()) . '.' . $fileExt;
        $saveFile = $path . '/' . $fileName;
        file_put_contents($saveFile, $content);
        $status = 0;
        if (config('xy_oss.status')) {
            switch (config('xy_oss.service_provider')) {
                case 'aliyun':
                    $status = self::updateAliyunOss($saveFile, $fileName);
                    break;
                case 'qcloud':
                    $status = self::updateTencentQcloud($saveFile);
                    break;
                case 'qiniu':
                    $status = self::updateQiniu($saveFile, $fileName);
                    break;
            }
        }
        $filesModel = new FilesModel;
        $filesModel->type = 99;
        $filesModel->is_admin = 1;
        $filesModel->uid = Session::get('AdminUser.uid', 'bsadmin');
        $filesModel->path = $saveFile;
        $filesModel->status = $status;
        $filesModel->ext = $fileExt;
        $filesModel->mime = $ContentType;
        if ($filesModel->save()) {
            $ret = [
                'msg'       =>  '上传成功',
                'code'      =>  0,
                'data'      =>  [
                    'type'      =>  $action,
                    'path'      =>  '/' . $saveFile,
                    'file_type' =>  $ContentType,
                    'file_size' =>  $FileSize,
                    'url'       =>  config('web.imgurl') . '/' . $saveFile
                ]
            ];
        } else {
            @unlink(root_path() . 'public' . $saveFile);
            $ret = ['msg' => '保存失败', 'code' => -100];
        }
        return $ret;
    }

    public static function updateAliyunOss($url, $saveName)
    {
        $url = str_replace('/public/', '/', $url);
        $url = str_replace('/uploads', 'uploads', $url);
        try {
            $ossClient = new AliyunOssClient(config('xy_oss.key'), config('xy_oss.secret'), config('xy_oss.region'));

            $ossClient->putObject(config('xy_oss.bucket'), $url, file_get_contents($url));
            $status = 1;
        } catch (AliyunOssException $e) {
            $status = 2;
        }
        return $status;
    }
    public static function updateTencentQcloud($url)
    {
        $url = str_replace('/public/', '/', $url);
        $url = str_replace('/uploads', 'uploads', $url);
        $cosClient = new QcloudClient([
            'region' => config('xy_oss.region'),
            'schema' => 'https', //协议头部，默认为http
            'credentials' => [
                'secretId'  => config('xy_oss.secret'),
                'secretKey' => config('xy_oss.key')
            ]
        ]);
        try {
            $result = $cosClient->putObject([
                'Bucket' => config('xy_oss.bucket'),
                'Key' => $url,
                'Body' => file_get_contents($url)
            ]);
            $status = 1;
        } catch (\Exception $e) {
            p($e->getMessage());
            p($e->getLine());
            $status = 2;
        }
        return $status;
    }
    public static function updateQiniu($url, $saveName)
    {
        $url = str_replace('/public/', '/', $url);
        $url = str_replace('/uploads', 'uploads', $url);
        // 初始化Auth状态
        $auth = new QiniuClient(config('xy_oss.key'), config('xy_oss.secret'));
        $token = $auth->uploadToken(config('xy_oss.bucket'));
        $uploadMgr = new QiniuUploadManager();
        //        list($ret, $err) = $uploadMgr->putFile($token, $url, file_get_contents($url));
        list($ret, $err) = $uploadMgr->putFile($token, $url, $url);
        if ($err !== null) {
            $status = 2;
        } else {
            $status = 1;
        }
        return $status;
    }
}
